黑暗執行緒有說明 IEnumerable + yield 的好處
善用 yield return 省時省 CPU 省 RAM,打造高效率程式
但是必須知道IEnumerable的特性,要不然就像雙面刃
一不小心挖坑給自己跳囉
IEnumerable 是
延遲執行(deferred execution)或 惰性求值(lazy evaluation)
簡單的說 就是 每次都會再執行一次
來個一般用List範例
void Main()
{
var store = new DemoStore();
var productList = store.GetProducts();
var total = productList.Count();
$"Total products {total}".Dump();
foreach (var product in productList)
{
$"{product.Id},{product.Name}".Dump();
}
}
public class DemoStore
{
public List<Product> GetProducts()
{
List<Product> result = new List<Product>();
for (int i = 0; i < 5; i++)
{
$"{i}產生Product中".Dump();
result.Add(new Product()
{
Id = i,
Name = $"Pro {i}"
});
}
return result;
}
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
// Define other methods and classes here
執行結果是
0產生Product中
1產生Product中
2產生Product中
3產生Product中
4產生Product中
Total products 5
0,Pro 0
1,Pro 1
2,Pro 2
3,Pro 3
4,Pro 4
然後看完 IEnumerable + yield 覺得好棒就這樣改
void Main()
{
var store = new DemoStore();
var productList = store.GetProducts();
var total = productList.Count();
$"Total products {total}".Dump();
foreach (var product in productList)
{
$"{product.Id},{product.Name}".Dump();
}
}
public class DemoStore
{
public IEnumerable<Product> GetProducts()
{
int count = 5;
for (int i = 0; i < count; i++)
{
$"{i}產生Product中".Dump();
yield return new Product()
{
Id = i,
Name = $"Pro {i}"
};
}
}
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
執行結果是
0產生Product中
1產生Product中
2產生Product中
3產生Product中
4產生Product中
Total products 5
0產生Product中
0,Pro 0
1產生Product中
1,Pro 1
2產生Product中
2,Pro 2
3產生Product中
3,Pro 3
4產生Product中
4,Pro 4
有想到會變成這樣嗎 需然每次有用到 GetProducts的時候
就會再跑一次 如果是查資料庫 就會讀取資料庫兩次
這個範例來說 就是要在適合地方加上ToList
var productList = store.GetProducts().ToList();
這樣就可以了
搞懂延遲執行
[.NET]快快樂樂學LINQ系列前哨戰-延遲執行 (Deferred Execution)
[.NET] LINQ 的延遲執行 (Deferred Execution)
所以IEnumerable + yield 是好東西 但是要知道如何應對這雙面刃
最後這也是 程式是照你寫的跑不是照你想的跑